#include "wifi_apstation.h"
#include "WebServer.h"
#include "HC_SR04.h"
#include "esp_netif.h"
#include "OTA.h"

// 定义存储IP地址的数组
#define INET_ADDRSTRLEN (16) // 足够大以存储IPv4地址和空字符
char ip_address_str[INET_ADDRSTRLEN];

char ip_str[INET_ADDRSTRLEN]; // 定义足够大的字符数组来存储IP地址字符串

static const char *TAG = "wifi";


bool apstion_ap_fail_retry;
uint8_t ap_fail_retrycnt;

// 获取MAC地址并转换为字符串的函数
void get_mac_address_as_string(char *mac_str, size_t max_size)
{
    uint8_t mac[6];
    esp_wifi_get_mac(ESP_IF_WIFI_AP, mac); // 获取AP模式下的MAC地址
    snprintf(mac_str, max_size, "%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}



/** 事件回调函数
 * @param arg   用户传递的参数
 * @param event_base    事件类别
 * @param event_id      事件ID
 * @param event_data    事件携带的数据
 * @return 无
*/
static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
{   
    if(event_base == WIFI_EVENT)
    {
        switch (event_id)
        {
        case WIFI_EVENT_STA_START:      //WIFI以STA模式启动后触发此事件
            esp_wifi_connect();         //启动WIFI连接
            break;
        case WIFI_EVENT_STA_CONNECTED:  //WIFI连上路由器后，触发此事件
            ESP_LOGI(TAG, "connected to AP");
            break;
        case WIFI_EVENT_AP_START:

            ESP_LOGI(TAG, "AP start");
            break;
        case WIFI_EVENT_STA_DISCONNECTED:   //WIFI从路由器断开连接后触发此事件
            esp_wifi_connect();             //继续重连
            ESP_LOGI(TAG,"connect to the AP fail,retry now");

            ap_fail_retrycnt++; //重连计数

            if(ap_fail_retrycnt >= 5) //重连5次后，进入ap模式
            {
                ap_fail_retrycnt = 0;
                ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP) );         //设置工作模式为ap
                ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_ap_config) );   //设置wifi配置
                ESP_ERROR_CHECK(esp_wifi_start() );                 
            }

            WiFiInoCfgStatus = 0; //密码错误则重进ap模式
            break;
        default:
            break;
        }
    }
    if(event_base == IP_EVENT)                  //IP相关事件
    {
        switch(event_id)
        {
            case IP_EVENT_STA_GOT_IP:           //只有获取到路由器分配的IP，才认为是连上了路由器
                ESP_LOGI(TAG,"get ip address");


            ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
            ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
            
            // 使用ip4addr_ntoa将IP地址转换为字符串
            
            esp_ip4addr_ntoa(&event->ip_info.ip, ip_str, INET_ADDRSTRLEN);
            
            // 现在你可以使用'%s'来打印IP地址字符串
            printf("Got IP: %s\n", ip_str);
            
            // 如果你需要将IP地址字符串存储到另一个数组中
            strcpy(ip_address_str, ip_str); // 确保ip_address_str已经定义并且足够大IP: %s\n", ip_address_str); // 打印IP地址以验证

            
            WiFiInoCfgStatus = 1;  //配网完成后标志位置1  调试时往往会将该位置0
            write_nvs_byte(NVS_WiFiInoCfgStatus_NAMESPACE, NVS_WiFiInoCfgStatus, WiFiInoCfgStatus);
            ESP_LOGI(TAG, "联网成功后从NVS中读出的WiFiInoCfgStatus值: %d", WiFiInoCfgStatus);
            Write_nvs_str(NVS_WiFi_Ino_NAMESPACE, NVS_SSID_KEY, WiFiIno.ssid);   //联网成功后，存储wifi名称和wifi密码
            Write_nvs_str(NVS_WiFi_Ino_NAMESPACE, NVS_PASSWORD_KEY, WiFiIno.password);

            
            //写入LocationBatIno.Devid
            ESP_LOGI(TAG, "写入NVS前LocationBatIno.device_id的值为: %s", LocationBatIno.device_id);
            Write_nvs_str(NVS_DEV_Id_NAMESPACE, NVS_DEV_ID_KEY, LocationBatIno.device_id);
            // LocationBatIno.device_id = 0;
            Read_nvs_str(NVS_DEV_Id_NAMESPACE, NVS_DEV_ID_KEY, LocationBatIno.device_id,16);
            ESP_LOGI(TAG, "读取NVS后LocationBatIno.device_id的值为: %s", LocationBatIno.device_id);

            //写入LocationBatIno.building_id
            ESP_LOGI(TAG, "写入NVS前LocationBatIno.building_id的值为: %ld", LocationBatIno.building_id);
            Write_nvs_int(NVS_Box_Ino_NAMESPACE, NVS_BUILDING_KEY, LocationBatIno.building_id);
            LocationBatIno.building_id = 0;
            Read_nvs_int(NVS_Box_Ino_NAMESPACE, NVS_BUILDING_KEY, &LocationBatIno.building_id);
            ESP_LOGI(TAG, "读取NVS后LocationBatIno.building_id的值为: %ld", LocationBatIno.building_id);

            //写入LocationBatIno.floor_id
            Write_nvs_int(NVS_Box_Ino_NAMESPACE, NVS_FLOOR_KEY, LocationBatIno.floor_id);
            LocationBatIno.floor_id = 0;
            Read_nvs_int(NVS_Box_Ino_NAMESPACE, NVS_FLOOR_KEY, &LocationBatIno.floor_id);
            ESP_LOGI(TAG, "读取NVS后LocationBatIno.floor_id的值为: %ld", LocationBatIno.floor_id);

            //写入LocationBatIno.room_id
            Write_nvs_int(NVS_Box_Ino_NAMESPACE, NVS_ROOM_KEY, LocationBatIno.room_id);
            LocationBatIno.room_id = 0;
            Read_nvs_int(NVS_Box_Ino_NAMESPACE, NVS_ROOM_KEY, &LocationBatIno.room_id);
            ESP_LOGI(TAG, "读取NVS后LocationBatIno.room_id的值为: %ld", LocationBatIno.room_id);

            //写入LocationBatIno.device_location_id
            Write_nvs_int(NVS_Box_Ino_NAMESPACE, NVS_ROOM_POSTION_KEY, LocationBatIno.device_location_id);
            LocationBatIno.device_location_id = 0;
            Read_nvs_int(NVS_Box_Ino_NAMESPACE, NVS_ROOM_POSTION_KEY, &LocationBatIno.device_location_id);
            ESP_LOGI(TAG, "读取NVS后LocationBatIno.device_location_id的值为: %ld", LocationBatIno.device_location_id);

            //写入LocationBatIno.device_type_id
            Write_nvs_int(NVS_Box_Ino_NAMESPACE, NVS_BOX_TYPE_KEY, LocationBatIno.device_type_id);
            LocationBatIno.device_type_id = 0;
            Read_nvs_int(NVS_Box_Ino_NAMESPACE, NVS_BOX_TYPE_KEY, &LocationBatIno.device_type_id);
            ESP_LOGI(TAG, "读取NVS后LocationBatIno.device_type_id的值为: %ld", LocationBatIno.device_type_id);




            /*WIFI连接成功*/
            xEventGroupSetBits(data_analy_event_group, WiFiConnect_Success);

            mqtt_app_start(); //wifi连接成功后接入AWS云服务

            break;

        }
    }
}

wifi_config_t wifi_sta_config = 
{ 

    .sta = 
    { 
        .threshold.authmode = WIFI_AUTH_WPA2_PSK,   //加密方式
        
        .pmf_cfg = 
        {
            .capable = true,
            .required = false
        },
    },
};

wifi_config_t wifi_ap_config =
{
    .ap = {
    // .ssid = "SLIQUE",
    // .ssid_len = 0,
    //.password = WIFI_AP_PASS,
    .channel = 1,
    .max_connection = 4,
    .authmode = WIFI_AUTH_OPEN, //设置为开放网络不需要密码
    .ssid_hidden = 0,  //不隐藏SSID
    },
};




esp_err_t wifi_apsta_init(void)
{   
    ESP_ERROR_CHECK(esp_netif_init());  //用于初始化tcpip协议栈
    ESP_ERROR_CHECK(esp_event_loop_create_default());       //创建一个默认系统事件调度循环，之后可以注册回调函数来处理系统的一些事件
    esp_netif_create_default_wifi_sta();    //使用默认配置创建STA对象
    esp_netif_create_default_wifi_ap();    //使用默认配置创建ap对象

    //初始化WIFI
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_AP_START, webserver_ap_start_handler, NULL); //进入ap_start连接时触发回调
    esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_START, webserver_sta_start_handler, NULL);

    //注册事件
    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT,ESP_EVENT_ANY_ID,&event_handler,NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT,IP_EVENT_STA_GOT_IP,&event_handler,NULL));


    char mac_str[18]; // 用于存储MAC地址字符串，足够的长度以容纳格式化后的MAC地址
    char new_mac_str[25];

    // 获取MAC地址字符串
    get_mac_address_as_string(mac_str, sizeof(mac_str));
    snprintf(new_mac_str, sizeof(new_mac_str), "SLIQUE_%s", mac_str);
    ESP_LOGI(TAG, "new_mac_str:%s", new_mac_str);

    // 设置SSID设为特定字符串+MAC地址的格式
    strncpy((char *)wifi_ap_config.ap.ssid, new_mac_str, sizeof(wifi_ap_config.ap.ssid));
    wifi_ap_config.ap.ssid_len = strlen(new_mac_str);


    //WIFI配置
    memset(&wifi_sta_config.sta.ssid, 0, sizeof(wifi_sta_config.sta.ssid));
    memcpy(wifi_sta_config.sta.ssid, WiFiIno.ssid, strlen(WiFiIno.ssid));
    memset(&wifi_sta_config.sta.password, 0, sizeof(wifi_sta_config.sta.password));
    memcpy(wifi_sta_config.sta.password, WiFiIno.password, strlen(WiFiIno.password));

    ESP_LOGI(TAG, "即将配网前wifi_sta_config.sta.ssid的值:%s", wifi_sta_config.sta.ssid);
    ESP_LOGI(TAG, "即将配网前wifi_sta_config.sta.password的值:%s", wifi_sta_config.sta.password);


    if(!WiFiInoCfgStatus)   //未配置过WiFi或配网失败时，进入ap模式
    {
        ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP) );         //设置工作模式为ap
        ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_ap_config) );   //设置wifi配置
        ESP_ERROR_CHECK(esp_wifi_start() );                         //启动WIFI
    }
    if(WiFiInoCfgStatus)   //若配置过wifi则进入sta模式尝试联网
    {
        //打开station模式，校验wifi名称和密码
        ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA) );         //设置工作模式为STA
        ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_sta_config) );   //设置wifi配置
        ESP_ERROR_CHECK(esp_wifi_start() );                         //启动WIFI
    }
      
    ESP_LOGI(TAG, "wifi_init_sta finished.");
    return ESP_OK;
}



